package com.jumi.microservice.controller;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jumi.microservice.common.base.BaseController;
import com.jumi.microservice.common.base.dto.BasePageResponse;
import com.jumi.microservice.common.base.dto.ResponseResult;
import com.jumi.microservice.common.constant.ImageResizeEnum;
import com.jumi.microservice.common.constant.ResultEnum;
import com.jumi.microservice.common.redis.RedisCache;
import com.jumi.microservice.common.utils.ImageResizeUtil;
import com.jumi.microservice.common.utils.ObjectUtils;
import com.jumi.microservice.common.utils.ResultGenerator;
import com.jumi.microservice.constant.*;
import com.jumi.microservice.domain.*;
import com.jumi.microservice.jwt.annon.IgnoreUrlsAnnon;
import com.jumi.microservice.mapper.GoodsMapper;
import com.jumi.microservice.service.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 我的服务Controller组件
 *
 * @author Administrator
 */
@RestController
@Api(tags = "C端我的服务相关接口")
@RequestMapping("/api/commodity/goods/serve")
public class MyServeController extends BaseController {

    /**
     * 商品收藏管理service组件
     */
    @Autowired
    private GoodsFavoritesService goodsFavoritesService;

    /**
     * 足迹管理service组件
     */
    @Autowired
    private GoodsFootprintService goodsFootprintService;

    @Autowired
    private GoodsMapper goodsMapper;

    @Autowired
    private SourceMaterialService sourceMaterialService;

    @Autowired
    private SourceClassifyConfig sourceClassifyConfig;

    @Autowired
    private RedisCache redisCache;

    /**
     * 商品spu管理service组件
     */
    @Autowired
    private GoodsService goodsService;

    /**
     * 库存管理service组件
     */
    @DubboReference
    private GoodsInventoryApi goodsInventoryApi;

    /**
     * 商品sku管理service组件
     */
    @Autowired
    private GoodsSkuService goodsSkuService;

    /**
     * 收藏商品
     *
     * @param goodsId 收藏商品ID
     * @return 返回结果成功与否
     */
    @ApiOperation(value = "收藏商品", notes = "收藏商品")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "goodsId", value = "商品id")
    })
    @PostMapping("/favorites/add")
    public ResponseResult<Boolean> addFavoritesGoods(@RequestParam("goodsId") Long goodsId) {
        goodsFavoritesService.addServeGoods(getApiUserId().longValue(), goodsId);
        return ResultGenerator.genSuccessResult(Boolean.TRUE);
    }

    /**
     * 批量收藏商品
     *
     * @param goodsIds 收藏商品ID集合
     * @return 返回结果成功与否
     */
    @ApiOperation(value = "批量收藏商品", notes = "批量收藏商品")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "goodsIds", value = "商品id集合")
    })
    @PostMapping("/favorites/batch")
    public ResponseResult<Boolean> batchAddServeGoods(@RequestParam("goodsIds") List<Long> goodsIds) {
        goodsFavoritesService.batchAddServeGoods(getApiUserId().longValue(), goodsIds);
        return ResultGenerator.genSuccessResult(Boolean.TRUE);
    }

    /**
     * 取消收藏商品
     *
     * @param goodsId 收藏商品ID
     * @return 返回结果成功与否
     */
    @ApiOperation(value = "取消收藏的商品", notes = "取消收藏的商品")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "goodsId", value = "商品id")
    })
    @PostMapping("/favorites/cancel")
    public ResponseResult<Boolean> cancelFavoritesGoods(@RequestParam("goodsId") Long goodsId) {
        goodsFavoritesService.cancelServeGoods(getApiUserId().longValue(), goodsId);
        return ResultGenerator.genSuccessResult(Boolean.TRUE);
    }

    /**
     * 列表展现收藏的商品
     *
     * @return 返回结果成功与否
     */
    @ApiOperation(value = "列表展现收藏的商品", notes = "列表展现收藏的商品")
    @GetMapping("/favorites/list")
    public BasePageResponse<List<GoodsFavoritesVO>> listFavoritesGoods(@RequestParam(defaultValue = "1") Integer page,
                                                                       @RequestParam(defaultValue = "10") Integer size) {
        List<GoodsFavoritesVO> goodsFavorites =
                convertGoodsFavoritesDtoList2VoList(goodsFavoritesService.listServeGoods(getApiUserId().longValue()));

        int rowCount = goodsFavorites.size();
        int pageCount;
        if (rowCount % size == NumberConstant.NUMBER_ZERO.intValue()) {
            pageCount = rowCount / size;
        } else {
            pageCount = rowCount / size + NumberConstant.NUMBER_ONE.intValue();
        }

        return ResultGenerator.genSuccessResultPage(
                goodsFavorites.stream()
                        .skip(size * (page - NumberConstant.NUMBER_ONE.intValue()))
                        .limit(size).collect(Collectors.toList())
                , Long.valueOf(goodsFavorites.size()), Long.valueOf(pageCount));
    }

    @ApiOperation(value = "添加足迹", notes = "添加足迹")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "goodsId", value = "商品id")
    })
    @PostMapping("/footprint/add")
    public ResponseResult<Boolean> addFootprint(@RequestParam("goodsId") Long goodsId) {
        goodsFootprintService.FootprintAdd(getApiUserId().longValue(), goodsId);
        return ResultGenerator.genSuccessResult(Boolean.TRUE);
    }


    @ApiOperation(value = "删除足迹", notes = "删除足迹")
    @ApiImplicitParam(name = "footprintId", value = "足迹id")
    @DeleteMapping("/footprint/delete")
    public ResponseResult<Boolean> deleteFootprint(@RequestParam("footprintId") Long footprintId) {
        goodsFootprintService.FootprintDelete(footprintId);
        return ResultGenerator.genSuccessResult(Boolean.TRUE);
    }


    @ApiOperation(value = "足迹列表", notes = "足迹列表")
    @GetMapping("/footprint/list")
    public BasePageResponse listFootprints(
            @RequestParam(defaultValue = "1") Integer page,
            @RequestParam(defaultValue = "10") Integer size) {
        LambdaQueryWrapper<GoodsFootprintDO> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(GoodsFootprintDO::getMemberId, getApiUserId().longValue());
        wrapper.orderByDesc(GoodsFootprintDO::getBroTime);

        IPage<GoodsFootprintDO> pageInfo = goodsFootprintService.page(new Page<>(page, size), wrapper);
        //spuid集合
        List<Long> goodsSpuIds = new ArrayList<>();
        for (GoodsFootprintDO goodsFootprintDO : pageInfo.getRecords()) {
            goodsSpuIds.add(goodsFootprintDO.getGoodsId());
        }

        List<Long> goodsSkuIds = new ArrayList<>();
        if (goodsSpuIds.size() > NumberConstant.NUMBER_ZERO.intValue()) {
            goodsSkuIds = goodsService.getSkuIdListBySpuIds(goodsSpuIds);
        }

        Map<Long, List<GoodsSpuInventoryDTO>> spuInventoryMap = new HashMap<>(pageInfo.getRecords().size());
        if (goodsSkuIds.size() > NumberConstant.NUMBER_ZERO.intValue()) {
            //调用库存服务查询库存
            List<GoodsSpuInventoryDTO> goodsSpuInventories = goodsInventoryApi.goodsInventoryBySkuIds(goodsSkuIds);
            for (GoodsSpuInventoryDTO goodsSpuInventory : goodsSpuInventories) {
                if (!spuInventoryMap.containsKey(goodsSpuInventory.getSpuId())) {
                    List<GoodsSpuInventoryDTO> goodsSpuInventoryDTOList = new ArrayList<>();
                    goodsSpuInventoryDTOList.add(goodsSpuInventory);
                    spuInventoryMap.put(goodsSpuInventory.getSpuId(), goodsSpuInventoryDTOList);
                } else {
                    spuInventoryMap.get(goodsSpuInventory.getSpuId()).add(goodsSpuInventory);
                }
            }
        }

        // 判断是否开启虚拟销量
        int enableVirtualNum = redisCache.getCacheObject(GoodsKeyConstant.GOODS_VIRTUALNUM_KEY);

        for (GoodsFootprintDO goodsFootprintDO : pageInfo.getRecords()) {
            //查询商品信息
            GoodsDO goods = goodsMapper.selectById(goodsFootprintDO.getGoodsId());
            goodsFootprintDO.setGoodsName(goods.getGoodsName());

            Object cacheObject = redisCache.getCacheObject(GoodsKeyConstant.POSTAGEGOODS + goods.getId());
            if (!Objects.isNull(cacheObject)) {
                goodsFootprintDO.setGoodsPrice(BigDecimal.ZERO);
            } else {
                goodsFootprintDO.setGoodsPrice(goods.getGoodsPrice());
            }

            goodsFootprintDO.setGoodsImage(ImageResizeUtil.imageResize(goods.getGoodsImage(), ImageResizeEnum.LIST));
            //市场价
            goodsFootprintDO.setGoodsMarketprice(goods.getGoodsMarketprice());
            //商品描述
            goodsFootprintDO.setGoodsDescription(goods.getGoodsDescription());
            //计算销量
            if (spuInventoryMap.containsKey(goodsFootprintDO.getGoodsId())) {
                List<GoodsSpuInventoryDTO> goodsSpuInventoryDtoList = spuInventoryMap.get(goodsFootprintDO.getGoodsId());
                Integer storage = NumberConstant.NUMBER_ZERO.intValue();
                Integer saleStorage = NumberConstant.NUMBER_ZERO.intValue();
                for (GoodsSpuInventoryDTO goodsSpuInventory : goodsSpuInventoryDtoList) {
                    if (goodsSpuInventory.getSaledStorage() != null) {
                        storage += goodsSpuInventory.getSaledStorage();
                    }
                    if (goodsSpuInventory.getStockQuantity() != null) {
                        saleStorage += goodsSpuInventory.getStockQuantity();
                    }
                }

                if (enableVirtualNum == NumberConstant.NUMBER_ONE.intValue()) {
                    Integer virtualNum = goodsSkuService.countVirtualNumBySpuId(goodsFootprintDO.getGoodsId());
                    if (virtualNum != null) {
                        storage += virtualNum;
                    }
                }

                goodsFootprintDO.setSaledStorage(storage);
                goodsFootprintDO.setSaleStorage(saleStorage);
            } else {
                goodsFootprintDO.setSaledStorage(NumberConstant.NUMBER_ZERO.intValue());
                goodsFootprintDO.setSaleStorage(NumberConstant.NUMBER_ZERO.intValue());
            }


        }
        return ResultGenerator.genSuccessResultPage(pageInfo.getRecords(), pageInfo.getTotal());
    }

    @ApiOperation(value = "C端素材列表下拉", notes = "C端素材列表下拉")
    @GetMapping("/sourceMaterial/sourceListByName")
    public ResponseResult<List<SourceDropVO>> sourceListByName(@RequestBody SourceDropVO vo) {
        LambdaQueryWrapper<SourceMaterialDO> wrapper = Wrappers.lambdaQuery();
        wrapper.and(i -> {
            i.like(StringUtils.isNotEmpty(vo.getSpuGoodsName()), SourceMaterialDO::getSpuGoodsName, vo.getSpuGoodsName())
                    .or()
                    .like(StringUtils.isNotEmpty(vo.getSpuGoodsName()), SourceMaterialDO::getMaterialDescription, vo.getSpuGoodsName());
        });
        //商品分类id
        wrapper.eq(vo.getCategoryId() != null && vo.getCategoryId() != 0, SourceMaterialDO::getCategoryId, vo.getCategoryId());
        wrapper.eq(SourceMaterialDO::getStatus, StatusEnum.STATUS_YES.getCode());
        wrapper.eq(SourceMaterialDO::getIsDel, StatusEnum.STATUS_NO.getCode());
        wrapper.orderByDesc(SourceMaterialDO::getId, SourceMaterialDO::getUpdateTime);
        List<SourceMaterialDO> list = sourceMaterialService.list(wrapper);
        return ResultGenerator.genSuccessResult(
                list.stream().map(s -> {
                    SourceDropVO svo = new SourceDropVO();
                    svo.setId(s.getId());
                    svo.setSpuGoodsName(s.getSpuGoodsName());
                    svo.setMaterialDescription(vo.getMaterialDescription());
                    return svo;
                }).collect(Collectors.toList()));
    }


    @ApiOperation(value = "C端-素材/素材库分页接口", notes = "C端-素材/素材库分页接口")
    @GetMapping("/sourcePage")
    @IgnoreUrlsAnnon("/sourcePage")
    public JSONObject sourcePage(@RequestParam(defaultValue = "0") Integer page,
                                 @RequestParam(defaultValue = "0") Integer size,
                                 SourceMaterialVO vo) {
        JSONObject o = new JSONObject();
        o.put("code", ResultEnum.SUCCESS.getCode());
        o.put("msg", ResultEnum.SUCCESS.getMessage());
        LambdaQueryWrapper<SourceMaterialDO> wrapper = Wrappers.lambdaQuery();
        if(vo.getSourceClassfy()!=null) {
            wrapper.like(StringUtils.isNotEmpty(vo.getSpuGoodsName()), SourceMaterialDO::getSpuGoodsName, vo.getSpuGoodsName());
            wrapper.like(StringUtils.isNotEmpty(vo.getMaterialDescription()), SourceMaterialDO::getMaterialDescription, vo.getMaterialDescription());
        }else{
            if(StringUtils.isNotEmpty(vo.getSpuGoodsName())) {
                wrapper.and(i -> {
                    i.like(SourceMaterialDO::getSpuGoodsName, vo.getSpuGoodsName())
                            .or()
                            .like(SourceMaterialDO::getMaterialDescription, vo.getSpuGoodsName());
                });
            }
        }
        //商品分类id
        wrapper.eq(vo.getCategoryId() != null && vo.getCategoryId() != 0, SourceMaterialDO::getCategoryId, vo.getCategoryId());
        //商品spuid
        wrapper.eq(vo.getSpuGoodsId() != null, SourceMaterialDO::getSpuGoodsId, vo.getSpuGoodsId());
        //素材分类
        wrapper.eq(vo.getSourceClassfy() != null, SourceMaterialDO::getSourceClassfy, vo.getSourceClassfy());
        //素材模块  0全部,1商品素材，2发现推荐
        if (vo.getModuleType() != null) {
            wrapper.in(SourceMaterialDO::getModuleType, getModuleType(vo.getModuleType()));
        }
        wrapper.eq(SourceMaterialDO::getStatus, StatusEnum.STATUS_YES.getCode());
        wrapper.eq(SourceMaterialDO::getIsDel, StatusEnum.STATUS_NO.getCode());
        wrapper.orderByDesc(SourceMaterialDO::getUpdateTime);
        IPage<SourceMaterialDO> page1 = sourceMaterialService.page(new Page<>(page, size), wrapper);
        //获取分类的关联商品信息
        List<GoodsDO> goods = goodsMapper.selectList(
                Wrappers.<GoodsDO>lambdaQuery()
                        .in(CollectionUtil.isNotEmpty(page1.getRecords()), GoodsDO::getId, page1.getRecords().stream().map(SourceMaterialDO::getSpuGoodsId).collect(Collectors.toList())));
        o.put("data", pos2Vos(page1.getRecords(), sourceClassifyConfig.getClassify(), goods));
        o.put("total", page1.getTotal());
        o.put("classfy", sourceClassifyConfig.getClassify());
        return o;
    }

    /**
     * 将收藏的商品DTO对象集合转换为VO对象集合
     *
     * @param goodsFavorites 收藏的商品DTO集合
     * @return List<GoodsFavoritesVO> 收藏的商品VO对象集合
     */
    private List<GoodsFavoritesVO> convertGoodsFavoritesDtoList2VoList(List<GoodsFavoritesDTO> goodsFavorites) {
        List<GoodsFavoritesVO> targetGoods = null;
        try {
            targetGoods = ObjectUtils.convertList(goodsFavorites, GoodsFavoritesVO.class);
        } catch (Exception e) {
            ExceptionEnum.FAIL_CHANGE.newException();
        }
        return targetGoods;
    }


    /**
     * 列表对象转化
     *
     * @param pos
     * @return
     */
    private List<SourceMaterialVO> pos2Vos(List<SourceMaterialDO> pos, List<SourceClassifyVO> classify, List<GoodsDO> goods) {
        return pos.stream().map(p -> {
            SourceMaterialVO vo = null;
            try {
                vo = p.clone(SourceMaterialVO.class);
                SourceClassifyVO cvo = classify.stream().filter(ca -> ca.getClassifyType().equals(p.getSourceClassfy())).findAny().orElse(null);
                if (cvo != null) {
                    vo.setSourceClassfyName(cvo.getClassifyName());
                }
                vo.setSourceMaterialImage(ImageResizeUtil.batchImageResize(vo.getSourceMaterialImage(), ImageResizeEnum.LIST));
                //商品主图/商品名称 根据商品id取 未取表中存的
                GoodsDO good = goods.stream().filter(g -> p.getSpuGoodsId().equals(g.getId())).findAny().orElse(null);
                if (good != null) {
                    vo.setGoodsImage(ImageResizeUtil.imageResize(good.getGoodsImage(),ImageResizeEnum.LARGE));
                    vo.setSpuGoodsName(good.getGoodsName());
                }
                packDelayTime(p, vo);
            } catch (Exception e) {
                ExceptionEnum.FAIL_CHANGE.newException();
            }
            return vo;
        }).collect(Collectors.toList());
    }

    /**
     * 根据素材模块封装素材条件 商品素材: 模块为0,1; 素材库: 模块为0,2; 否则: 全部
     *
     * @param type
     * @return
     */
    private List<Integer> getModuleType(Integer type) {
        List<Integer> ints = new ArrayList<>(3);
        ints.add(0);
        if (1 == type) {
            ints.add(1);
        } else if (2 == type) {
            ints.add(2);
        } else {
            ints.add(1);
            ints.add(2);
        }
        return ints;
    }

    private void packDelayTime(SourceMaterialDO po, SourceMaterialVO vo){
        LocalDateTime fromDateTime = po.getUpdateTime();
        LocalDateTime toDateTime = LocalDateTime.now();
        LocalDateTime tempDateTime = LocalDateTime.from( fromDateTime );

        Long months = tempDateTime.until( toDateTime, ChronoUnit.MONTHS);
        tempDateTime = tempDateTime.plusDays( months );

        long days = tempDateTime.until( toDateTime, ChronoUnit.DAYS);
        tempDateTime = tempDateTime.plusDays( days );

        long hours = tempDateTime.until( toDateTime, ChronoUnit.HOURS);
        tempDateTime = tempDateTime.plusHours( hours );

        long minutes = tempDateTime.until( toDateTime, ChronoUnit.MINUTES);
        tempDateTime = tempDateTime.plusMinutes( minutes );

        long seconds = tempDateTime.until( toDateTime, ChronoUnit.SECONDS);

        if(months>0){
            vo.setDelayTime(months+"月前");
            return;
        }
        if(days>0){
            vo.setDelayTime(days+"天前");
            return;
        }
        if(hours>0){
            vo.setDelayTime(hours+"小时前");
            return;
        }

        if(minutes>0){
            vo.setDelayTime(minutes+"分钟前");
            return;
        }
        if(seconds>0){
            vo.setDelayTime(seconds+"秒前");
            return;
        }
    }
}
